class Watcher {
  constructor(data, key) {
    this.data = data;
    this.key = key;
    Dep.target = this;
    this.get();
    Dep.target = null;
  }
  get() {
    return this.data[this.key];
  }
  update() {
    console.log(`重新获取数据${this.get()}并更新视图`);
  }
}

class Dep {
  constructor() {
    this.subs = [];
  }
  depend(watcher) {
    this.subs.push(watcher);
  }
  notify() {
    this.subs.forEach((watcher) => {
      watcher.update();
    });
  }
  static target = null;
}
let dep = null;
function defineReactive(data, key, value) {
  dep = new Dep();
  observe(value);
  Object.defineProperty(data, key, {
    get: function reactiveGetter() {
      if (Dep.target) {
        console.log("第一次获取，将watcher收集");
        dep.depend(Dep.target);
      } else {
        console.log("获取数据" + key);
      }
      return value;
    },
    set: function reactiveSetter(newVal) {
      if (value===newVal) return
      console.log("设置数据" + key + "并通知视图更新");
      value = newVal;
      dep.notify();
    },
  });
}

class Observer {
  constructor(data) {
    this.data = data;
    if (Array.isArray(this.data)) {
      this.observerArray(this.data);
    } else {
      this.walk(this.data);
    }
  }
  observerArray(data) {
    data.forEach((item) => {
      observe(item);
    });
  }
  walk(data) {
    for (let key of Object.keys(data)) {
      defineReactive(data, key, data[key]);
    }
  }
}

function observe(data) {
  if (typeof data !== "object" || data === null) return;
  new Observer(data);
}

function Vue(options) {
  this._data = options.data;
  for (let key of Object.keys(this._data)) {
    Object.defineProperty(this, key, {
      get: function proxyGetter() {
        return this._data[key];
      },
      set: function proxySetter(newVal) {
        this._data[key] = newVal;
      },
    });
  }

  observe(this._data);
}

const vm = new Vue({
  data: {
    name: "lingHua",
    age: 18,
    movieList: [
      {
        id: "001",
        movieName: "肖申克的救赎",
      },
      {
        id: "002",
        movieName: "盗梦空间",
      },
    ],
    weather: {
      type: "晴天",
      temperature: 28,
    },
  },
});

//创建组件测试函数
function createComponent() {
  new Watcher(vm, "name");
  // new Watcher(vm, "movieList");
}

//修改数据的测试函数
function updateData() {
  vm.name = "凌华";
  // vm.movieList = [
  //   {
  //     id: "001",
  //     movieName: "朝花夕誓",
  //   },
  //   {
  //     id: "002",
  //     movieName: "游戏人生Zero",
  //   },
  // ];
}
// 模拟创建组件和使用插值语法
createComponent();
//模拟修改数据然后更新视图，模板函数没有写
updateData();
